feat: Add Cloud Backup and Restore via GitHub Gists#3826
feat: Add Cloud Backup and Restore via GitHub Gists#3826Martí Climent (marticliment) merged 27 commits into
Conversation
- Added IdentityModel.OidcClient and Octokit packages. - Implemented SecureTokenManager for secure GitHub token storage using PasswordVault. - Created GitHubAuthService to handle OIDC authentication flow with GitHub, including a WinUIBrowser for system browser interaction. - Configured protocol activation for 'unigetui-auth://' in App.xaml.cs and Package.appxmanifest to handle OAuth callback. - Added initial structure for GistService to create Gists using Octokit. Note: UI integration and explicit testing steps were to be skipped as per request.
Adds functionality to allow users to: - Log in with their GitHub account using OAuth. - Backup their UniGetUI settings to a private GitHub Gist. - Restore their UniGetUI settings from a GitHub Gist. Key changes include: - New services: GitHubAuthService for handling GitHub OAuth and GitHubBackupService for Gist operations. - UI additions to Internet settings for GitHub login/logout. - UI additions to Backup settings for Gist backup/restore buttons. - Enhancements to SettingsEngine for string-based import/export. - New settings keys for GitHub username and Gist ID.
This commit introduces a new feature allowing users to back up and restore their UniGetUI settings and installed packages to a private GitHub Gist.
Key changes:
- **GitHub Authentication:**
- Implements an OAuth2 flow to securely connect to the user's GitHub account.
- Uses a local loopback server for the OAuth redirect, improving the user experience.
- Securely stores the OAuth token and user information.
- **Backup and Restore Logic:**
- Creates a private GitHub Gist to store backup files.
- Backs up both settings (`unigetui.settings.json`) and a list of installed packages (`unigetui.packages.ubundle`).
- Allows restoring settings and packages separately. Restoring packages loads them into the "Package Bundles" page for installation.
- **UI Enhancements:**
- The "Backup" settings page is redesigned as "Backup and Restore".
- Provides clear login/logout functionality and status indicators.
- Adds separate buttons for backing up, restoring settings, and restoring packages.
- **Build Process:**
- The build script now generates a `Secrets.cs` file for the GitHub OAuth client details from environment variables, which is git-ignored.
it includes updates to several source files in the UniGetUI project, such as SecureTokenManager.cs for security settings, SettingsEngine_ImportExport.cs for settings management, and Internet.xaml along with its code-behind file Internet.xaml.cs for UI adjustments related to internet settings. These changes ensure the codebase remains consistent and up-to-date after the removal of the documentation file.
|
Thanks! |
|
Hey TheGuy (@theguy000), I've been looking at the implementation, and overall I really like it, thanks!
For both things, I can take care of them, and once I have I will merge the PR and publish a beta release so the features can be tested out. |
|
Would you be interested in having a "merge settings" option in addition to an "overwrite local settings" option? If both are willing, I'm willing to open a PR to this branch for the addition of settings merges as well (since unset settings don't exist). |
…its identifier locally. Multiple user support added
You mean vscode-like settings sync? |
|
I mean not a bad feature to have. |
|
Probably? My VS Code hasn't synced in almost two years so I don't really know... But, like, settings from the server wouldn't (or would, depending on a setting / dialog button) overwrite locally set settings, but if they're not there locally the server setting would apply. I guess this isn't really a common use case, but it might help with (as previously mentioned) multi-device support - updates would be merged as well, so the latest configuration is always synced to all devices. |
|
To be honest, I thought about settings sync, but then I thougt it would be expected for different devices to have different settings (for example, I don't have vcpkg or npm on my laptop, but I do on my desktop), so I guess it kinda makes sense to not sync settings across devices. Perhaps they can also be backed up to GitHub like with the bundles (like TheGuy (@theguy000)'s original implementation), but I don't see an immediate benefit (again, you'd be importing the settings on a new machine (or same machine with an erased OS, otherwhise settings wouldn't have been erased), with different software installed, etc.) |
|
How about this -
|
Yeah, I think you're probably right. |
|
1 and 2 are already intrinsic on the multi-device support, and 4, it is very easily achievable by loading different backups and installing the wanted packages. 3, While intrastructure-wise it is very easy to implement (even more with the multi-file support already done), I still think it will not be useful, and will confuse users (I have received complaints of nonworking bundles because people were confusing bundles with import/export settings, and they are located on different parts of the UI, I don't think it is worth the hassle) |
c0b7013
into
Devolutions:main
There was a problem hiding this comment.
Pull Request Overview
Adds cloud backup and restore functionality using private GitHub Gists, alongside enhanced local backup support and automated secret generation.
- Introduces
GitHubAuthServiceandGitHubBackupServicefor OAuth2 login and gist-based backups - Updates settings UI (
Backup.xaml) to handle separate cloud and local backup flows - Implements build‐time secrets file generation via PowerShell and project file targets
Reviewed Changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/UniGetUI/UniGetUI.csproj | Added target to generate Secrets.Generated.cs |
| src/UniGetUI/Services/generate-secrets.ps1 | Powershell script to emit client ID/secret code files |
| src/UniGetUI/Services/GitHubBackupService.cs | New service to create, update, and list GitHub Gist backups |
| src/UniGetUI/Services/GitHubAuthService.cs | New OAuth2 flow with loopback listener and token storage |
| src/UniGetUI/Pages/SettingsPages/GeneralPages/Backup.xaml | Extended UI for cloud/local backups |
| src/UniGetUI/Pages/SettingsPages/GeneralPages/Backup.xaml.cs | Logic for cloud and local backup button handlers |
| src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs | Split backup logic into BackupPackages_CLOUD and _LOCAL |
| src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | Refactored open/save bundle methods to string-based APIs |
Comments suppressed due to low confidence (4)
src/UniGetUI/Services/UserAvatar.cs:165
- [nitpick] Local variable
GHClientshould use camelCase (e.g.,ghClientorgitHubClient) to align with C# naming conventions.
var GHClient = authClient.CreateGitHubClient();
src/UniGetUI/Pages/SettingsPages/GeneralPages/Backup.xaml.cs:256
- New cloud backup methods (
BackupPackages_CLOUD,BackupPackages_LOCAL) lack corresponding unit tests. Consider adding tests to cover these scenarios.
var packagesContent = await InstalledPackagesPage.GenerateBackupContents();
src/UniGetUI/Services/GitHubBackupService.cs:103
- The fallback empty array
[]is not valid C# syntax. Consider usingEnumerable.Empty<string>()ornew string[0]for an empty fallback.
.Select(f => $"{f.Key.Split(' ')[^1]} ({CoreTools.FormatAsSize(f.Value.Size)})") ?? [];
src/UniGetUI/Pages/SettingsPages/GeneralPages/Backup.xaml.cs:187
- [nitpick] Fetching all user gists on each call can be slow for users with many gists. Consider caching the gist list or limiting the request scope.
);
|
When will the new version be released? |
|
next beta in a few days, stable will depend on how many issues are found, but expect at least a week from the beta release. |




TODO
This pull request introduces a new feature allowing users to back up and restore their UniGetUI settings and installed packages to the cloud using private GitHub Gists.
What's New:
update an existing one.
Key Technical Changes:
GitHubAuthService: A new service to handle the entire GitHub OAuth2 authentication process, using a localhost loopback redirect to receive the callback.GitHubBackupService: A new service responsible for creating, retrieving, and updating the backup Gist.SecureTokenManager: A new helper class to securely store and retrieve the GitHub token from the PasswordVault.Any user suspected of farming GitHub activity with crypto purposes will get banned. Submitting broken code wastes the contributors' time, who have to spend their free time reviewing, fixing, and testing code that does not even compile breaks other features, or does not introduce any useful changes. I appreciate your understanding.
Closes #XXXX
Relates to #3726